package com.imut.lagain.service;
import org.slf4j.LoggerFactory;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.imut.lagain.entity.AccessLog;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 访问日志服务接口
 */
public interface IAccessLogService extends IService<AccessLog> {
    
    /**
     * 记录访问日志
     * @param userId 用户ID
     * @param path 访问路径
     * @param method 请求方法
     * @param ipAddress IP地址
     * @param userAgent 用户代理
     * @param referer 来源页面
     * @param statusCode 状态码
     * @param responseTime 响应时间（毫秒）
     * @param requestParams 请求参数
     * @return 创建的访问日志
     */
    AccessLog logAccess(Long userId, String path, String method, String ipAddress, 
                       String userAgent, String referer, Integer statusCode, 
                       Long responseTime, String requestParams);
    
    /**
     * 记录访问日志（简化版本）
     * @param userId 用户ID
     * @param path 访问路径
     * @param method 请求方法
     * @param ipAddress IP地址
     * @param userAgent 用户代理
     * @param statusCode 状态码
     * @param responseTime 响应时间（毫秒）
     * @param errorMessage 错误信息
     * @return 创建的访问日志
     */
    AccessLog logAccess(Long userId, String path, String method, String ipAddress, 
                       String userAgent, int statusCode, long responseTime, String errorMessage);
    
    /**
     * 根据用户ID分页查询访问日志
     * @param userId 用户ID
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    IPage<AccessLog> getLogsByUserId(Long userId, Page<AccessLog> page);
    
    /**
     * 根据访问路径分页查询
     * @param path 访问路径
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    IPage<AccessLog> getLogsByPath(String path, Page<AccessLog> page);
    
    /**
     * 根据请求方法分页查询
     * @param method 请求方法
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    IPage<AccessLog> getLogsByMethod(String method, Page<AccessLog> page);
    
    /**
     * 根据IP地址分页查询
     * @param ipAddress IP地址
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    IPage<AccessLog> getLogsByIpAddress(String ipAddress, Page<AccessLog> page);
    
    /**
     * 根据状态码分页查询
     * @param statusCode 状态码
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    IPage<AccessLog> getLogsByStatusCode(Integer statusCode, Page<AccessLog> page);
    
    /**
     * 根据访问时间范围查询
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    IPage<AccessLog> getLogsByAccessTimeBetween(LocalDateTime startTime, LocalDateTime endTime, Page<AccessLog> page);
    
    /**
     * 根据响应时间范围查询
     * @param minResponseTime 最小响应时间
     * @param maxResponseTime 最大响应时间
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    IPage<AccessLog> getLogsByResponseTimeBetween(Long minResponseTime, Long maxResponseTime, Page<AccessLog> page);
    
    /**
     * 统计访问次数
     * @param userId 用户ID（null表示所有用户）
     * @param path 访问路径（null表示所有路径）
     * @param method 请求方法（null表示所有方法）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 访问次数
     */
    Long countAccess(Long userId, String path, String method, LocalDateTime startTime, LocalDateTime endTime);
    
    /**
     * 根据条件查询访问日志
     * @param userId 用户ID
     * @param path 访问路径
     * @param method 请求方法
     * @param ipAddress IP地址
     * @param statusCode 状态码
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param page 页码
     * @param size 每页大小
     * @return 访问日志分页列表
     */
    IPage<AccessLog> getLogsByConditions(Long userId, String path, String method, String ipAddress, 
                                        Integer statusCode, LocalDateTime startTime, LocalDateTime endTime, 
                                        int page, int size);
    
    /**
     * 统计错误日志（4xx和5xx状态码）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 错误日志列表
     */
    List<AccessLog> getErrorLogs(LocalDateTime startTime, LocalDateTime endTime);
    
    /**
     * 分页查询错误日志（4xx和5xx状态码）
     * @param page 分页参数
     * @return 错误日志分页列表
     */
    IPage<AccessLog> getErrorLogs(Page<AccessLog> page);
    
    /**
     * 获取最近的访问日志
     * @param limit 限制数量
     * @return 最近的访问日志列表
     */
    List<AccessLog> getRecentLogs(Integer limit);
    
    /**
     * 统计各路径的访问次数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 路径访问统计
     */
    List<Map<String, Object>> countByPath(LocalDateTime startTime, LocalDateTime endTime);
    
    /**
     * 统计各IP地址的访问次数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return IP访问统计
     */
    List<Map<String, Object>> countByIpAddress(LocalDateTime startTime, LocalDateTime endTime);
    
    /**
     * 统计各状态码的数量
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 状态码统计
     */
    List<Map<String, Object>> countByStatusCode(LocalDateTime startTime, LocalDateTime endTime);
    
    /**
     * 统计各用户的访问次数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 用户访问统计
     */
    List<Map<String, Object>> countByUserId(LocalDateTime startTime, LocalDateTime endTime);
    
    /**
     * 计算平均响应时间
     * @param path 访问路径（null表示所有路径）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 平均响应时间（毫秒）
     */
    Double getAverageResponseTime(String path, LocalDateTime startTime, LocalDateTime endTime);
    
    /**
     * 统计独立访客数（根据IP地址）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 独立访客数
     */
    Long countUniqueVisitors(LocalDateTime startTime, LocalDateTime endTime);
    
    /**
     * 获取热门访问路径
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param limit 限制数量
     * @return 热门路径列表
     */
    List<Map<String, Object>> getPopularPaths(LocalDateTime startTime, LocalDateTime endTime, Integer limit);
    
    /**
     * 获取活跃用户列表
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param limit 限制数量
     * @return 活跃用户列表
     */
    List<Map<String, Object>> getActiveUsers(LocalDateTime startTime, LocalDateTime endTime, Integer limit);
    
    /**
     * 清理过期日志
     * @param beforeTime 清理此时间之前的日志
     * @return 清理的日志数量
     */
    int cleanupOldLogs(LocalDateTime beforeTime);
    
    /**
     * 记录GET请求访问
     * @param userId 用户ID
     * @param path 访问路径
     * @param ipAddress IP地址
     * @param userAgent 用户代理
     * @param referer 来源页面
     * @param statusCode 状态码
     * @param responseTime 响应时间
     * @return 创建的访问日志
     */
    AccessLog logGetAccess(Long userId, String path, String ipAddress, String userAgent, String referer, Integer statusCode, Long responseTime);
    
    /**
     * 记录POST请求访问
     * @param userId 用户ID
     * @param path 访问路径
     * @param ipAddress IP地址
     * @param userAgent 用户代理
     * @param referer 来源页面
     * @param statusCode 状态码
     * @param responseTime 响应时间
     * @param requestParams 请求参数
     * @return 创建的访问日志
     */
    AccessLog logPostAccess(Long userId, String path, String ipAddress, String userAgent, String referer, Integer statusCode, Long responseTime, String requestParams);
    
    /**
     * 记录PUT请求访问
     * @param userId 用户ID
     * @param path 访问路径
     * @param ipAddress IP地址
     * @param userAgent 用户代理
     * @param referer 来源页面
     * @param statusCode 状态码
     * @param responseTime 响应时间
     * @param requestParams 请求参数
     * @return 创建的访问日志
     */
    AccessLog logPutAccess(Long userId, String path, String ipAddress, String userAgent, String referer, Integer statusCode, Long responseTime, String requestParams);
    
    /**
     * 记录DELETE请求访问
     * @param userId 用户ID
     * @param path 访问路径
     * @param ipAddress IP地址
     * @param userAgent 用户代理
     * @param referer 来源页面
     * @param statusCode 状态码
     * @param responseTime 响应时间
     * @return 创建的访问日志
     */
    AccessLog logDeleteAccess(Long userId, String path, String ipAddress, String userAgent, String referer, Integer statusCode, Long responseTime);
    
    /**
     * 获取系统访问统计概览
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 访问统计概览
     */
    Map<String, Object> getAccessStatistics(LocalDateTime startTime, LocalDateTime endTime);
}
